//
//  Obstacle.h
//  NSESolver
//
//  Created by Patrick Zulian on 5/5/11.
//  Copyright 2011 ICS - USI - Lugano. All rights reserved.
//

#ifndef NSESolver_Obstacle_H
#define NSESolver_Obstacle_H

#include <vector>
#include "Types.h"

namespace nsesolver {
    
    
    
    
    //Forward dec
    class CFDProblem;
    
    
    enum ObstacleCellType {
        OSouthWest = 1,
        OWest,
        ONorthWest,
        ONorth,
        ONorthEast,
        OEast,
        OSouthEast,
        OSouth,
        ONull
    };
    
    
    class Obstacle {
    private:
        typedef struct obstacle_cell {
            int i, j;
            ObstacleCellType type;
            
        } obstacle_cell;
        
        Matrix< bool > obsCellMap;
        std::vector< obstacle_cell > cells;
    public:
        
        typedef std::vector< obstacle_cell >::const_iterator ConstObsCellIter; 
        
        /**
         * The empty Constructor
         */
        Obstacle(const int imax, const int jmax);
        
        
        /**
         * The Destructor
         */
        ~Obstacle();
        
        void setBoundary(CFDProblem &problem);
        void setPBoundary(CFDProblem &problem);
        void setFGBoundary(Matrixd & F, Matrixd & G, const CFDProblem &problem);
        void addCell(int i, int j);
        
        void assignFlags();
        
        inline bool isObstacleCell(const int i, const int j) const
        {
            return obsCellMap(i, j);
        }

        
        inline ConstObsCellIter obsCellBegin() const
        {
            return cells.begin();
        }
        
        inline ConstObsCellIter obsCellEnd() const
        {
            return cells.end();
        }
        
        inline int xmax() const 
        {
            return obsCellMap.xmax();
        }
        
        inline int ymax() const 
        {
            return obsCellMap.ymax();
        }
        
        inline bool isInXRange(const int i) const
        {
            return i >= 0 && i < xmax();
        }
        
        
        inline bool isInYRange(const int j) const
        {
            return j >= 0 && j < ymax();
        }
        
        inline bool isInXYRange(const int i, const int j) const
        {
            return isInXRange(i) && isInYRange(j);
        }
        
//        inline void setContactBoundaryCells()
//        {
//            for (int i = 1; i < xmax()-1; i++) {
//                if (isObstacleCell(i, 1)) {
//                    obstacle_cell cell = { i, 0, ONull };
//                    cells.push_back(cell);
//                }
//                
//                if (isObstacleCell(i, ymax()-2)) {
//                    obstacle_cell cell = { i, ymax()-1, ONull };
//                    cells.push_back(cell);
//                }
//            }
//            
//            
//            for (int j = 1; j < ymax()-1; j++) {
//                if (isObstacleCell(1, j)) {
//                    obstacle_cell cell = { 0, j, ONull };
//                    cells.push_back(cell);
//                }
//                
//                if (isObstacleCell(xmax()-2, j)) {
//                    obstacle_cell cell = { xmax()-1, j, ONull };
//                    cells.push_back(cell);
//                }
//            }
//        }
    };
    
}

#endif //NSESolver_Obstacle_H
